package com.yl.order.helper;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Handler;
import android.text.TextUtils;

import com.google.gson.Gson;
import com.jeremyliao.liveeventbus.LiveEventBus;
import com.net.yl.entity.ActivateEntity;
import com.yl.common.utils.LogUtil;
import com.yl.order.App;
import com.yl.order.BuildConfig;
import com.yl.order.Constants;
import com.yl.order.entity.MqttMessageEntity;
import com.yl.order.interfaces.Callback;

import org.eclipse.paho.android.service.MqttAndroidClient;
import org.eclipse.paho.client.mqttv3.IMqttActionListener;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.IMqttToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;

import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

/**
 * create by cjx on 2024/6/21
 * desc:
 */
public class MqttServiceHelper {
    private final String TAG = "MQTT";

    private long reconnectTime = 30000L;

    public static final int CMD_SYNC_PRODUCT = 2101;

    private MqttAndroidClient mqttAndroidClient;
    private MqttConnectOptions mqttConnectOptions;

    private final String TOPIC_CMD_COMMON;

    private Callback<Boolean> connectCallback;

    private final Handler connectHandler = new Handler(msg -> {
        doClientConnection();
        return false;
    });

    private final IMqttActionListener listener = new IMqttActionListener() {
        @Override
        public void onSuccess(IMqttToken asyncActionToken) {
            log("MQTT连接成功");
            subscribe();
            if (connectCallback != null) {
                connectCallback.callback(true);
            }
        }

        @Override
        public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
            log("MQTT连接失败");
            connectHandler.sendEmptyMessageDelayed(0, reconnectTime);
            reconnectTime = reconnectTime * 2;
            if (connectCallback != null) {
                connectCallback.callback(false);
            }
        }
    };

    private static final class HelperHolder {
        static final MqttServiceHelper helper = new MqttServiceHelper();
    }

    public static MqttServiceHelper getInstance() {
        return HelperHolder.helper;
    }

    private final MqttCallback callback = new MqttCallback() {
        @Override
        public void messageArrived(String topic, MqttMessage message) {
            String payload = new String(message.getPayload(), StandardCharsets.UTF_8);
            log("收到消息： " + payload);
            MqttMessageEntity mqttMessageEntity = new Gson().fromJson(payload, MqttMessageEntity.class);
            if (mqttMessageEntity == null) {
                return;
            }

            if (topic.equals(TOPIC_CMD_COMMON)) {
                int[] cmd = mqttMessageEntity.getCmd();
                LiveEventBus.get(Constants.BUS_SYNC_DATA_ACTION).post(cmd);
            }
        }

        @Override
        public void deliveryComplete(IMqttDeliveryToken token) {

        }

        @Override
        public void connectionLost(Throwable arg0) {
            log("MQTT连接断开 ");
            if (connectCallback != null) {
                connectCallback.callback(false);
            }
            connectHandler.removeMessages(0);
            connectHandler.sendEmptyMessageDelayed(0, 5000);
        }
    };

    private MqttServiceHelper() {
        TOPIC_CMD_COMMON = "cmd/common/" + App.app.activateInfo.getSn();
    }

    private String userId; //用户ID，唯一标识符

    public void init(Callback<Boolean> connectCallback) {
        ActivateEntity activateInfo = App.app.activateInfo;
        if (TextUtils.isEmpty(activateInfo.getMqttUrl()) || TextUtils.isEmpty(activateInfo.getPwd())) {
            return;
        }
        this.connectCallback = connectCallback;
        SimpleDateFormat sdf = new SimpleDateFormat("MMddHHmm", Locale.CHINA);
        userId = activateInfo.getSn() + "-" + sdf.format(new Date());
//        mqttAndroidClient = new MqttAndroidClient(App.app, activateInfo.getMqttUrl(), userId);
        mqttAndroidClient = new MqttAndroidClient(App.app, BuildConfig.MQTT_URL, userId);
        mqttAndroidClient.setCallback(callback); //设置监听订阅消息的回调
        mqttConnectOptions = new MqttConnectOptions();
        // userid 固定时，可以设置成false， 不固定则需要设置成true
        mqttConnectOptions.setCleanSession(false); //设置是否清除缓存
        mqttConnectOptions.setConnectionTimeout(60); //设置超时时间，单位：秒
        mqttConnectOptions.setKeepAliveInterval(60); //设置心跳包发送间隔，单位：秒
        mqttConnectOptions.setUserName(activateInfo.getSn()); //设置用户名
        mqttConnectOptions.setPassword(activateInfo.getPwd().toCharArray()); //设置密码
        System.out.println("mqtt --- " + userId + ", " + BuildConfig.MQTT_URL + ", " + activateInfo.getSn() + ", " + activateInfo.getPwd());
        // last will message
        String disconnect = "{\"disconnect\":\"" + userId + "\"}";
        mqttConnectOptions.setWill("post/offline/" + activateInfo.getSn(), disconnect.getBytes(), 2, false);

        doClientConnection();
    }

    /**
     * 连接MQTT服务器
     */
    private void doClientConnection() {
        if (!mqttAndroidClient.isConnected() && hasNet()) {
            try {
                mqttAndroidClient.connect(mqttConnectOptions, null, listener);
            } catch (MqttException e) {
                error(e);
            }
        }
    }

    // 连接成功了， 开始订阅主题
    private void subscribe() {
        try {
            mqttAndroidClient.subscribe(TOPIC_CMD_COMMON, 1);
        } catch (Exception e) {
            error(e);
        }
    }

    /**
     * 判断网络是否连接
     */
    private boolean hasNet() {
        ConnectivityManager connectivityManager = (ConnectivityManager) App.app.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo info = connectivityManager.getActiveNetworkInfo();
        if (info != null && info.isAvailable()) {
            return true;
        } else {
            log("没有可用网络");
            /*没有可用网络的时候，延迟30秒再尝试重连*/
            new Handler().postDelayed(this::doClientConnection, 30000);
            return false;
        }
    }

    private void log(String log) {
        LogUtil.getInstance().log(TAG, log);
    }

    private void error(Exception e) {
        LogUtil.getInstance().log(TAG, e);
    }

}
